﻿using PressureTest.Model;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using fmtx.Framework.Web;
using fmtx.Framework.NoSqlHelper;
using System.Text.RegularExpressions;
using System.Net;
using PressureTest.AppCode;
using MongoDB.Driver.Builders;

namespace PressureTest
{
    public partial class MainForm : Form
    {
        public List<UserInfo> users;
        public List<TestAddress> testAddresss;
        SetParamter sp;
        public bool statu = true;
        public bool spisHide = false;
        private bool iserror = false;
        MongoOperation<UserInfoLog> userdb = new MongoOperation<UserInfoLog>();
        MongoOperation<TestResultLog> testdb = new MongoOperation<TestResultLog>();
        TimeLogService tls = new TimeLogService();
        Dictionary<string, int> tokenerror = new Dictionary<string, int>();
        public MainForm()
        {
            CheckForIllegalCrossThreadCalls = false;
            InitializeComponent();
            InitDB();
            if (!iserror)
            {
                ShowInfo();
            }
        }

        /// <summary>
        /// 初始化数据库（建立索引）
        /// </summary>
        private void InitDB()
        {
            try
            {
                var stat = userdb.MongoCollection.Database.Server.State;
                userdb.MongoCollection.Database.Server.Ping();

                var t_StatuCode_index = IndexKeys<TestResultLog>.Ascending(k => k.StatuCode);
                if (!testdb.MongoCollection.IndexExists(t_StatuCode_index))
                {
                    testdb.MongoCollection.EnsureIndex(t_StatuCode_index);
                }
                var t_Uname_index = IndexKeys<TestResultLog>.Ascending(k => k.Uname);
                if (!testdb.MongoCollection.IndexExists(t_Uname_index))
                {
                    testdb.MongoCollection.EnsureIndex(t_Uname_index);
                }
                var t_IsError_index = IndexKeys<TestResultLog>.Ascending(k => k.IsError);
                if (!testdb.MongoCollection.IndexExists(t_IsError_index))
                {
                    testdb.MongoCollection.EnsureIndex(t_IsError_index);
                }
                var u_StatuCode_index = IndexKeys<UserInfoLog>.Ascending(k => k.StatuCode);
                if (!userdb.MongoCollection.IndexExists(u_StatuCode_index))
                {
                    userdb.MongoCollection.EnsureIndex(u_StatuCode_index);
                }
                var u_Uname_index = IndexKeys<UserInfoLog>.Ascending(k => k.Uname);
                if (!userdb.MongoCollection.IndexExists(u_Uname_index))
                {
                    userdb.MongoCollection.EnsureIndex(u_Uname_index);
                }
            }
            catch (Exception e)
            {
                iserror = true;
                MessageBox.Show(e.Message);
                btnnew.Enabled = false;
            }
        }

        /// <summary>
        /// 根据灌入用户数据发起线程
        /// </summary>
        private void BeginThread()
        {
            if (sp.cbxresultdb.Checked)
            {
                userdb.MongoCollection.RemoveAll();
                testdb.MongoCollection.RemoveAll();
            }
            if (!string.IsNullOrEmpty(sp.txttokenurl.Text))
            {
                tls.Save();
                for (int i = 0; i < users.Count; i++)
                {
                    Thread th = new Thread(() => BeginUser());
                    th.Start();
                }
            }
            
            Thread sth = new Thread(() => RefreshInfo());
            sth.Start();
        }

        /// <summary>
        /// 用户登录授权
        /// </summary>
        private void BeginUser()
        {
            var user = users.Where(w=>w.IsUse==false).FirstOrDefault();
            user.IsUse = true;
            StringBuilder val = new StringBuilder();
            val.Append(sp.txtuname.Text);
            val.Append("=");
            val.Append(user.Uname);
            val.Append("&");
            val.Append(sp.txtpass.Text);
            val.Append("=");
            val.Append("123&");
            val.Append(sp.txtkey.Text);
            val.Append("=");
            UserInfoLog ui = new UserInfoLog();
            
            string tokenres = "";
            ui.Uname = user.Uname;
            RequestResult res;
            if (sp.cmbmethod.Text.ToUpper()=="POST")
            {
                res = WebHelper.PostHtmlFull(sp.txttokenurl.Text, val.ToString(), 120, Encoding.UTF8);
            }
            else
            {
                res = WebHelper.GetHtmlFull(string.Format("{0}?{1}", sp.txttokenurl.Text, val), 120, Encoding.UTF8);
            }
            ui.Error = res.Error;
            ui.Html = tokenres = res.Html;
            ui.StatuCode = res.StatusCode;
            ui.Cookies = res.Cookies;
            if (!string.IsNullOrEmpty(tokenres)&&sp.cmbtype.Text == "UrlParamter")
            {
                //记录登录成功！开始对页面压力请求！
                if (!string.IsNullOrEmpty(sp.txtreq.Text))
                {
                    MatchCollection matchs;
                    matchs = new Regex(sp.txtreq.Text, RegexOptions.Singleline | RegexOptions.IgnoreCase | RegexOptions.Compiled).Matches(tokenres);
                    if (matchs.Count>0)
                    {
                        ui.Token = matchs[Convert.ToInt32(sp.txtindex.Text ?? "0")].Groups[Convert.ToInt32(sp.txtcindex.Text ?? "0")].Value;
                    }
                }
                else
                {
                    ui.Token = tokenres;
                }
            }else if(sp.cmbtype.Text == "Cookie"){
                var token = res.Cookies[sp.txtkey.Text].Value;
                ui.Token = token;
            }
            else
            {
                user.IsUse = false;
            }
            if (!string.IsNullOrEmpty(ui.Token))
            {
                Thread th = new Thread(() => BeginTest(ui.Token, user.Uname,ui.Cookies));
                th.Start();
            }
            else
            {
                user.IsUse = false;
            }

            userdb.MongoCollection.Insert(ui, MongoDB.Driver.SafeMode.True);
            if (!string.IsNullOrEmpty(ui.Error))
            {
                if (!tokenerror.ContainsKey(ui.Uname) || tokenerror[ui.Uname]<3)
                {
                    if (tokenerror.ContainsKey(ui.Uname))
                    {
                        tokenerror[ui.Uname] += 1;
                    }
                    else
                    {
                        tokenerror.Add(ui.Uname, 1);
                    }
                    //5s后从新开始
                    Thread.Sleep(5000);
                    BeginUser();
                }
                
            }
        }

        /// <summary>
        /// 抛送测试数据
        /// </summary>
        /// <param name="token"></param>
        private void BeginTest(string token,string uname,CookieCollection cookies)
        {
            while (statu)
            {
                foreach (var item in testAddresss)
                {
                    TestResultLog trl = new TestResultLog();
                    trl.Uname = uname;
                    trl.Token = token;
                    trl.Url = item.Url;
                    RequestResult res;
                    if (sp.cmbtype.Text == "UrlParamter")
                    {
                        if (item.Method.ToUpper() == "POST")
                        {
                            res = WebHelper.PostHtmlFull(string.Format("{0}?{1}={2}", item.Url, sp.txtkey.Text, token),"", 120, Encoding.UTF8);
                        }
                        else
                        {
                            res = WebHelper.GetHtmlFull(string.Format("{0}?{1}={2}", item.Url, sp.txtkey.Text, token), 120, Encoding.UTF8);
                        }
                    }
                    else
                    {
                        if (item.Method.ToUpper() == "POST")
                        {
                            res = WebHelper.PostHtmlFull(item.Url, "", 120, Encoding.UTF8, cookies);
                        }
                        else
                        {
                            res = WebHelper.GetHtmlFull(item.Url, 120, Encoding.UTF8, cookies);
                        }
                    }
                    if (!string.IsNullOrEmpty(item.ErrorCode) &&!string.IsNullOrEmpty(res.Html)&& res.Html.Trim()==item.ErrorCode.Trim())
                    {
                        trl.IsError = true;
                    }
                    else if (trl.StatuCode==HttpStatusCode.OK)
                    {
                        trl.IsError = false;
                    }
                    //记录成功！
                    trl.Html = res.Html;
                    //记录失败！
                    trl.Error = res.Error;
                    trl.StatuCode = res.StatusCode;

                    testdb.MongoCollection.Insert(trl, MongoDB.Driver.SafeMode.True);
                }
            }
        }

        private void ShowInfo()
        {
            labucount.Text = users==null?"0":users.Count.ToString();
            labupcount.Text = userdb.Count(w => w.StatuCode == HttpStatusCode.OK ).ToString();
            labeucount.Text = userdb.Count(w => w.StatuCode != HttpStatusCode.OK ).ToString();
            labrqcount.Text = testdb.Count().ToString();
            labreqecount.Text = testdb.Count(w => w.StatuCode != HttpStatusCode.OK ||w.IsError==true).ToString();
            var ss = new TimeSpan(DateTime.Now.Ticks - tls.Get().ToLocalTime().Ticks);
            labreqcounttime.Text = ss.Days.ToString()+"天"+ss.Hours.ToString() + "小时" + ss.Minutes.ToString()+"分钟";    
        }

        private void RefreshInfo()
        { 
            while (statu)
            {
                ShowInfo();
                Thread.Sleep(2000);
            }
            btnnew.Enabled = true;
            MessageBox.Show("线程已经停止！");
        }

        private void btnstop_Click(object sender, EventArgs e)
        {
            statu = false;
            btnstop.Enabled = false;
        }

        private void btnclose_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            statu = false;
        }

        private void btnuxs_Click(object sender, EventArgs e)
        {
            UserLogForm ulf = new UserLogForm();
            ulf.Show();
        }

        private void btnrxs_Click(object sender, EventArgs e)
        {
            TestResultForm trf = new TestResultForm();
            trf.Show();
        }

        private void btnnew_Click(object sender, EventArgs e)
        {
            testAddresss = new List<TestAddress>();
            users = new List<UserInfo>();
            btnnew.Enabled = false;
            InstillForm ilf = new InstillForm(users);
            ilf.ShowDialog();
            if (users.Count>0)
            {
                sp = new SetParamter(this,testAddresss);
                sp.ShowDialog();
                if (spisHide)
                {
                    BeginThread();
                    btnstop.Enabled = true;
                }
                else
                {
                    btnnew.Enabled = true;
                }
            }
            else
            {
                btnnew.Enabled = true;
            }
        }

    }
}
